package com.example.yunpicture.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.yunpicture.model.dto.space.analyze.*;
import com.example.yunpicture.exception.BusinessException;
import com.example.yunpicture.exception.ErrorCode;
import com.example.yunpicture.exception.ThrowUtils;
import com.example.yunpicture.model.entity.Picture;
import com.example.yunpicture.model.entity.Space;
import com.example.yunpicture.model.entity.User;
import com.example.yunpicture.model.vo.space.analyze.*;
import com.example.yunpicture.service.PictureService;
import com.example.yunpicture.service.SpaceAnalyzeService;
import com.example.yunpicture.service.SpaceService;
import com.example.yunpicture.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 空间分析服务
 */
@Service
public class SpaceAnalyzeServiceImpl implements SpaceAnalyzeService {

    @Resource
    private UserService userService;

    @Resource
    private SpaceService spaceService;

    @Resource
    private PictureService pictureService;

    /**
     * 获取空间使用情况分析
     * @param spaceUsageAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwif(spaceUsageAnalyzeRequest==null,ErrorCode.NOT_FOUND_ERROR);
        //判断操作范围
        if (spaceUsageAnalyzeRequest.isQueryPublic()|| spaceUsageAnalyzeRequest.isQueryAll()){
            //校验用户权限（仅管理员）
            boolean isAdmin = userService.isAdmin(loginUser);
            ThrowUtils.throwif(!isAdmin,ErrorCode.NO_AUTH_ERROR);
            //补充查询
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("pic_size");
            //如果是查询公共图库
            if (!spaceUsageAnalyzeRequest.isQueryAll()){
                queryWrapper.isNull("space_id");
            }
            List<Object> pictureList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            long usedSize = pictureList.stream().mapToLong(size -> size instanceof Long ? (Long) size : 0).sum();
            long usedCount = pictureList.stream().mapToLong(count -> count instanceof Long ? (Long) count : 0).sum();
            //封装返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            spaceUsageAnalyzeResponse.setUsedSize(usedSize);
            spaceUsageAnalyzeResponse.setUsedCount(usedCount);
            spaceUsageAnalyzeResponse.setMaxSize(null);
            spaceUsageAnalyzeResponse.setMaxCount(null);
            spaceUsageAnalyzeResponse.setCountUsedRatio(null);
            spaceUsageAnalyzeResponse.setSizeUsedRatio(null);
            return spaceUsageAnalyzeResponse;
        }else {
            //校验参数
            Long spaceId = spaceUsageAnalyzeRequest.getSpaceId();
            ThrowUtils.throwif(spaceId==null||spaceId<0,ErrorCode.PARAMS_ERROR,"空间id不正确");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwif(space==null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");
            //校验空间权限
            spaceService.checkSpaceAuth(space,loginUser);
            //构造返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            spaceUsageAnalyzeResponse.setUsedSize(space.getTotalSize());
            spaceUsageAnalyzeResponse.setUsedCount(space.getTotalCount());
            spaceUsageAnalyzeResponse.setMaxSize(space.getMaxSize());
            spaceUsageAnalyzeResponse.setMaxCount(space.getMaxCount());
            double sizeUsageRatio = space.getMaxSize() * 100.0 / space.getTotalSize();
            spaceUsageAnalyzeResponse.setSizeUsedRatio(Double.parseDouble(String.format("%.2f", sizeUsageRatio)));
            double countUsageRatio = space.getMaxCount() * 100.0 / space.getTotalCount();
            spaceUsageAnalyzeResponse.setCountUsedRatio(Double.parseDouble(String.format("%.2f", countUsageRatio)));
            return spaceUsageAnalyzeResponse;
        }
    }

    /**
     * 获取空间图片分类分析
     * @param spaceCategoryAnalyzeRequest
     * @param loginUser
     * @return
     */

    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwif(spaceCategoryAnalyzeRequest==null,ErrorCode.PARAMS_ERROR);
        //检查权限
        checkSpaceAnalyzeAuth(spaceCategoryAnalyzeRequest,loginUser);
        //构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        //补充查询范围
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest,queryWrapper);
        queryWrapper.select("category AS category",
                "COUNT(*) AS count",
                "SUM(pic_size) AS total_size").groupBy("category");
        List<Map<String, Object>> maps = pictureService.getBaseMapper().selectMaps(queryWrapper);
        //返回结果
        return maps.stream().map(result -> {
            String category = result.get("category") != null ? (String) result.get("category") : "未分类";
            Long count = ((Number) result.get("count")).longValue();
            Long totalSize = ((Number) result.get("total_size")).longValue();
            return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
        }).collect(Collectors.toList());

    }

    /**
     * 获取标签分类情况
     * @param spaceTagAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwif(spaceTagAnalyzeRequest==null,ErrorCode.PARAMS_ERROR);
        //权限校验
        checkSpaceAnalyzeAuth(spaceTagAnalyzeRequest,loginUser);
        //构造查询
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        //补充查询范围
        fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest,queryWrapper);
        queryWrapper.select("tags");
        List<String> tagList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .filter(ObjectUtil::isNotNull)
                .map(Object::toString)
                .collect(Collectors.toList());
        Map<String, Long> tagCountMap = tagList.stream()
                .flatMap(tags -> JSONUtil.toList(tags, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));
        //处理查询结果
        return tagCountMap.entrySet().stream()
                .sorted((e1,e2)->Long.compare(e2.getValue(),e1.getValue()))
                .map(entry->new SpaceTagAnalyzeResponse(entry.getKey(),entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 获取图片大小分类情况
     * @param spaceSizeAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        ThrowUtils.throwif(spaceSizeAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        // 检查权限
        checkSpaceAnalyzeAuth(spaceSizeAnalyzeRequest, loginUser);

        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest, queryWrapper);

        // 查询所有符合条件的图片大小
        queryWrapper.select("pic_size");
        List<Long> picSizes = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .map(size -> ((Number) size).longValue())
                .collect(Collectors.toList());

        // 定义分段范围，注意使用有序 Map
        Map<String, Long> sizeRanges = new LinkedHashMap<>();
        sizeRanges.put("<100KB", picSizes.stream().filter(size -> size < 100 * 1024).count());
        sizeRanges.put("100KB-500KB", picSizes.stream().filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
        sizeRanges.put("500KB-1MB", picSizes.stream().filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
        sizeRanges.put(">1MB", picSizes.stream().filter(size -> size >= 1 * 1024 * 1024).count());

        // 转换为响应对象
        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }


    /**
     * 获取上传时间内的照片分类
     * @param spaceUserAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
        ThrowUtils.throwif(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceUserAnalyzeRequest, loginUser);

        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        Long userId = spaceUserAnalyzeRequest.getUserId();
        queryWrapper.eq(ObjUtil.isNotNull(userId), "userId", userId);
        fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, queryWrapper);

        // 分析维度：每日、每周、每月
        String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') AS period", "COUNT(*) AS count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) AS period", "COUNT(*) AS count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') AS period", "COUNT(*) AS count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的时间维度");
        }

        // 分组和排序
        queryWrapper.groupBy("period").orderByAsc("period");

        // 查询结果并转换
        List<Map<String, Object>> queryResult = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return queryResult.stream()
                .map(result -> {
                    String period = result.get("period").toString();
                    Long count = ((Number) result.get("count")).longValue();
                    return new SpaceUserAnalyzeResponse(period, count);
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取空间使用排行分析
     * @param spaceRankAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        ThrowUtils.throwif(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 仅管理员可查看空间排行
        ThrowUtils.throwif(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR, "无权查看空间排行");
        // 构造查询条件
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "space_name", "user_id", "total_size")
                .orderByDesc("total_size")
                .last("LIMIT " + spaceRankAnalyzeRequest.getTopN()); // 取前 N 名
        // 查询结果
        return spaceService.list(queryWrapper);
    }

    /**
     * 权限校验
     * @param spaceAnalyzeRequest
     * @param loginUser
     */
    @Override
    public void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        //如果是分析全部或者公共
        if (spaceAnalyzeRequest.isQueryAll()||spaceAnalyzeRequest.isQueryPublic()){
            //仅管理员可用
            ThrowUtils.throwif(userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        }else {
            //个人图库分析
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwif(spaceId==null||spaceId<0,ErrorCode.PARAMS_ERROR);
            //判断空间是否存在
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwif(space==null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");
            //校验是否有空间权限
            spaceService.checkSpaceAuth(space,loginUser);
        }
    }

    /**
     * 根据分析范围补充查询条件
     * @param spaceAnalyzeRequest
     * @param queryWrapper
     */
    @Override
    public void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
        //查询全部
        if (spaceAnalyzeRequest.isQueryAll()){
            return;
        }
        //查询公共图库
        if (spaceAnalyzeRequest.isQueryPublic()){
            queryWrapper.isNull("space_id");
            return;
        }
        //查询私人空间
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        if (spaceId!=null){
            queryWrapper.eq("space_id",spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR,"未指定查询范围");
    }
}
